<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			body {
				margin: 0px;
				padding: 0px;
			}

			svg {
				border: 1px solid #CCCCCC;
			}

			foreignObject {
				overflow: visible;
			}

			.model {
				/* font-size: 12px;
				transform: scale(0.63,0.63) ;
				*font-size: 10px; */
				/* background-color: #0000FF; */
				border: 2px solid #038FCE;
				border-radius: 4px;
				/* position: absolute; */
				background-color: #fff;
				-webkit-user-select: none;
				-moz-user-select: none;
				-ms-user-select: none;
				user-select: none;

			}

			.tablename:hover {
				/* background-color: #F0F8FF; */
				cursor: move;
			}

			.model .tablename {
				font-size: 10px;
				font-weight: bold;
				border-bottom: 1px solid #038FCE;
				padding: 2px 3px 3px 2px;
				text-align: center;
				background-color: #FF7F41;
			}

			.model .columns {
				padding: 5px;
			}

			.model .columns ul {
				list-style-type: none;
				padding: 0px;
				margin: 0px;
				font-size: 10px;
				/* font-weight: 500; */
			}

			.model .columns ul li {
				text-indent: 2px;
				overflow: hidden;
				/* min-height: 18px; */
			}
		</style>
	</head>
	<body>
		<svg id="s" version="1.1" baseProfile="full" width="4000" height="4000" xmlns="http://www.w3.org/2000/svg">
			<defs>
				<marker id='markerArrow' markerWidth='13' markerHeight='13' refx='2' refy='6' orient='auto'>
					<path d='M2,2 L2,11 L10,6 L2,2' style='fill:#000' />
				</marker>
			</defs>
		</svg>
	</body>
</html>
<script src="core.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
	var SVG_NS = "http://www.w3.org/2000/svg"
	var svg = document.getElementById("s");
	var registry = new Registry();

	class Table {
		constructor(data) {
			svg = document.getElementById("s");
			this.svg = svg;
			//安装主体
			let el = this.makeTable(data.meta, data.x, data.y);
			this.el = el;
			let self = this;
			//设置连接点
			let position = this.getPosition()
			this.connectPointGroup = new ConnectPointGroup(position.x, position.y, this.height);
			//安装连接点
			this.connectPointGroup.install();
			//默认隐藏连接点
			this.connectPointGroup.hide()


			//监听事件
			var pt = svg.createSVGPoint(),
				doc = svg.ownerDocument;
			var root = doc.rootElement || doc.body || svg;
			var xlate, txStartX, txStartY, mouseStart;
			var xforms = el.transform.baseVal;

			//鼠标划过事件
			el.onmouseover = function(evt) {
				//显示连接点
				self.connectPointGroup.show()
			}
			//鼠标移开事件
			el.onmouseout = function(evt) {
				self.connectPointGroup.hide()
			}

			//鼠标按下事件
			el.addEventListener('mousedown', startMove, false);

			function startMove(evt) {
				//显示连接点
				self.connectPointGroup.show()
				root.addEventListener('mousemove', handleMove, false);
				root.addEventListener('mouseup', finishMove, false);

				xlate = xforms.numberOfItems > 0 && xforms.getItem(0);
				if (!xlate || xlate.type != SVGTransform.SVG_TRANSFORM_TRANSLATE) {
					xlate = xforms.createSVGTransformFromMatrix(svg.createSVGMatrix());
					xforms.insertItemBefore(xlate, 0);
				}

				txStartX = xlate.matrix.e;
				txStartY = xlate.matrix.f;
				mouseStart = inElementSpace(evt);
				fireEvent('dragstart');

				//W3C阻止冒泡方法 
				evt = evt || window.event;
				if (evt.stopPropagation) {
					evt.stopPropagation();
				} else {
					evt.cancelBubble = true; //IE阻止冒泡方法  
				}
			}

			function handleMove(evt) {
				var point = inElementSpace(evt);
				let x = txStartX + point.x - mouseStart.x;
				let y = txStartY + point.y - mouseStart.y;
				xlate.setTranslate(x, y);
				//移动连接点
				self.dragCallback(x, y)
				fireEvent('drag');
			}

			function finishMove(evt) {
				
				var point = inElementSpace(evt);
				let x = txStartX + point.x - mouseStart.x;
				let y = txStartY + point.y - mouseStart.y;
				
				window.registry.update(data.meta.tableName,{x:x,y:y})
				root.removeEventListener('mousemove', handleMove, false);
				root.removeEventListener('mouseup', finishMove, false);
				fireEvent('dragend');
			}

			function fireEvent(eventName) {
				var event = new Event(eventName);
				event.detail = {
					x: xlate.matrix.e,
					y: xlate.matrix.f
				};
				return el.dispatchEvent(event);
			}

			// Convert mouse position from screen space to coordinates of el
			function inElementSpace(evt) {
				pt.x = evt.clientX;
				pt.y = evt.clientY;
				return pt.matrixTransform(el.parentNode.getScreenCTM().inverse());
			}
		}

		dragCallback(x, y) {
			console.log("实时位置：" + x + "," + y)
			this.connectPointGroup.move(x, y)
		}

		makeTable(meta, x, y) {
			this.g = document.createElementNS(SVG_NS, "g")
			this.g.setAttribute("transform", "translate(" + x + "," + y + ")")
			//创建foreignobject
			let foreignObject = new ForeignObject();
			//创建model
			let tm = new TableModel(meta)
			foreignObject.appendChild(tm);
			this.g.appendChild(foreignObject.toElement());
			//安装
			this.svg.appendChild(this.g);
			console.log(tm.model.clientHeight)
			this.height = tm.model.clientHeight;
			//设置模型容器高度
			foreignObject.setHeight(tm.model.clientHeight)
			return this.g;
		}

		getPosition() {
			let transform = this.el.getAttribute("transform");
			let xy = transform.replace("translate(", "").replace(")", "").split(",");
			return {
				x: parseInt(xy[0]),
				y: parseInt(xy[1])
			}
		}
	}

	//画线	
	function makeLine(el) {
		if (!el) return console.error('makeDraggable() needs an element');
		var svg = el;
		while (svg && svg.tagName != 'svg') svg = svg.parentNode;
		if (!svg) return console.error(el, 'must be inside an SVG wrapper');
		var pt = svg.createSVGPoint(),
			doc = svg.ownerDocument;

		var root = doc.rootElement || doc.body || svg;
		var xlate, txStartX, txStartY, mouseStart;
		var xforms = el.transform.baseVal;

		el.addEventListener('mousedown', startMove, false);

		var polyline = null;

		function startMove(evt) {
			//线的起点
			
			polyline = new Polyline();
			let startX = evt.pageX;
			let startY = evt.pageY;
			//搜索附近的连接点，并吸附
			let nebarConnect = getNearbyConnectPoint(evt.clientX, evt.clientY);
			if (nebarConnect) {
				startX = nebarConnect.x;
				startY = nebarConnect.y;
			}else{
					//销毁线段
					polyline.destroy()
				}
			polyline = new Polyline(startX, startY)
			svg.appendChild(polyline.toElement());
			root.addEventListener('mousemove', handleMove, false);
			root.addEventListener('mouseup', finishMove, false);

			function handleMove(evt) {
				let endX = evt.pageX;
				let endY = evt.pageY;
				//搜索附近的连接点，并吸附
				let nebarConnect = getNearbyConnectPoint(endX, endY);
				if (nebarConnect) {
					endX = nebarConnect.x;
					endY = nebarConnect.y;
				}
				polyline.move(endX, endY)
			}

			function finishMove(evt) {
				let endX = evt.pageX;
				let endY = evt.pageY;
				console.log("画线：",evt.pageX)
				console.log("画线：",evt.pageY)
				//搜索附近的连接点，并吸附
				let nebarConnect = getNearbyConnectPoint(endX, endY);
				if (nebarConnect) {
					//吸附
					endX = nebarConnect.x;
					endY = nebarConnect.y;
				}else{
					//销毁线段
					polyline.destroy()
				}
				polyline.move(endX, endY)

				root.removeEventListener('mousemove', handleMove, false);
				root.removeEventListener('mouseup', finishMove, false);
				//fireEvent('dragend');
			}

			function fireEvent(eventName) {
				var event = new Event(eventName);
				event.detail = {
					x: xlate.matrix.e,
					y: xlate.matrix.f
				};
				return el.dispatchEvent(event);
			}

			// Convert mouse position from screen space to coordinates of el
			function inElementSpace(evt) {
				// pt.x = evt.clientX;
				// pt.y = evt.clientY;
				// return pt.matrixTransform(el.parentNode.getScreenCTM().inverse());
			}
		}
	}

	/**
	 * 搜索最近的连接点
	 * @param {Object} x
	 * @param {Object} y
	 */
	function getNearbyConnectPoint(x, y) {
		let cps = document.getElementsByTagName("circle");
		for (let i = 0; i < cps.length; i++) {
			let cp = cps[i];
			let cpX = cp.getAttribute("cx");
			let cpY = cp.getAttribute("cy");
			//console.log("X:" + x + "附近目标：" + cpX)
			//console.log("Y:" + y + "附近目标：" + cpY)
			if (Math.abs(cpX - x) < 20 && Math.abs(cpY - y) < 20) {
				return {
					x: cpX,
					y: cpY
				};
			}
		}
		return null;
	}
	makeLine(document.getElementById("s"))

	var template = {
		x: 0,
		y: 0,
		meta: {
			tableName: "input_wms_entry",
			tableComment: "WMS入库",
			columns: [{
					"columnName": "ID",
					"primaryKey": true,
					"columnComment": "ID"
				},
				{
					"columnName": "Latest_storage_documents",
					"primaryKey": false,
					"columnComment": "最新入库单据"
				},
				{
					"columnName": "Document_number",
					"primaryKey": false,
					"columnComment": "单据编号"
				},
				{
					"columnName": "document_type",
					"primaryKey": false,
					"columnComment": "单据类型"
				}
			]
		}
	}

	var template2 = {
		x: 200,
		y: 200,
		meta: {
			tableName: "input_wms_entry",
			tableComment: "WMS入库",
			columns: [{
					"columnName": "ID",
					"primaryKey": true,
					"columnComment": "ID"
				},
				{
					"columnName": "Latest_storage_documents",
					"primaryKey": false,
					"columnComment": "最新入库单据"
				},
				{
					"columnName": "Document_number",
					"primaryKey": false,
					"columnComment": "单据编号"
				},
				{
					"columnName": "document_type",
					"primaryKey": false,
					"columnComment": "单据类型"
				}
			]
		}
	}
	// let t = new Table(template);
	// let t2 = new Table(template2);

	//接入数据
	function group(source) {
		var map = new Map();
		let arr = [];
		for (var i = 0; i < source.length; i++) {
			let t = source[i];
			let table = map.get(t.tableName)
			if (table == null) {
				table = {
					tableName: t.tableName,
					tableComment: t.tableComment,
					columns: []
				};
				map.set(t.tableName, table)
			}
			table.columns.push({
				columnName: t.columnName,
				primaryKey: t.primaryKey,
				columnComment: t.columnComment
			});
		}
		return map;
	}
</script>
<script src="tableMeta.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
	var ts = group(tableMetaSource)
	let i = 0;
	let h = 0;
	let w = 0;
	for (var [k, v] of ts) {
		console.log(v)
		if (i % 10 == 0&&i>0) {
			h++;
			w = 0;
		}
		let t = v;
		console.log(k,v)
		let model = {
			x: w * 300,
			y: h * 400,
			meta: t
		};
		new Table(model)
		i++;
		w++;
	}
</script>
